package servicepage

import (
	"encoding/json"
	"time"

	"advertoper/db"
	"advertoper/errorcode"

	"doubimeizhi.com/datatable"
	"doubimeizhi.com/utility"

	log "github.com/cihub/seelog"
)

func (p *ServicePageInfoService) init() {
	p.pages = make(map[string]*ServicePageInfoItem)
	appkeys := p.getAppKeys()
	for _, appkey := range appkeys {
		if page := p.getMaxServicePageInfoItemFromDB(appkey); page != nil {
			p.pages[appkey] = page
		}
	}
}

func (p *ServicePageInfoService) getAppKeys() []string {
	dtq := datatable.NewDataTableQuery()
	dtq.SetTableName("service_page")
	dtq.PushField(&datatable.FiledItem{Alias: "appkey", Field: "distinct(appkey)"})
	sql, values := dtq.GenerateSQL()
	mysqlHelper := db.GetMysqlHelper()
	appkeys := make([]string, 0, 0)
	if results, err := mysqlHelper.Query(sql, values...); err == nil {
		appkeys = make([]string, 0, len(results))
		for _, dt := range results {
			appkey := mysqlHelper.GetColString(dt, "appkey")
			appkeys = append(appkeys, appkey)
		}
	}
	return appkeys
}

func (p *ServicePageInfoService) getMaxServicePageInfoItemFromDB(appkey string) *ServicePageInfoItem {
	dtq := datatable.NewDataTableQuery()
	dtq.SetTableName("service_page")
	dtq.SetPage(0, 1)
	dtq.PushField(&datatable.FiledItem{Alias: "sid", Field: "sid", OrderBy: datatable.DESC})
	dtq.PushField(&datatable.FiledItem{Alias: "appkey", Field: "appkey"})
	dtq.PushField(&datatable.FiledItem{Alias: "version_id", Field: "version_id"})
	dtq.PushField(&datatable.FiledItem{Alias: "start_tick", Field: "start_tick"})
	dtq.PushField(&datatable.FiledItem{Alias: "end_tick", Field: "end_tick"})
	dtq.PushField(&datatable.FiledItem{Alias: "items", Field: "items"})
	dtq.PushField(&datatable.FiledItem{Alias: "status", Field: "status"})
	dtq.PushCondition("appkey = ?", appkey)
	sql, values := dtq.GenerateSQL()
	mysqlHelper := db.GetMysqlHelper()
	if results, err := mysqlHelper.Query(sql, values...); err == nil {
		if len(results) > 0 {
			page := &ServicePageInfoItem{}
			page.Sid = mysqlHelper.GetColInt64(results[0], "sid")
			page.AppKey = mysqlHelper.GetColString(results[0], "appkey")
			page.VersionId = mysqlHelper.GetColInt64(results[0], "version_id")
			page.StartTick = mysqlHelper.GetColInt64(results[0], "start_tick")
			page.EndTick = mysqlHelper.GetColInt64(results[0], "end_tick")
			page.Status = mysqlHelper.GetColInt(results[0], "status")
			args := mysqlHelper.GetColString(results[0], "items")
			items := make([]map[string]interface{}, 0, 0)
			if err := json.Unmarshal([]byte(args), &items); err != nil {
				log.Warnf("items: %s Unmarshal error: %s", args, err.Error())
			}
			page.Items = items
			return page
		}
	} else {
		log.Warnf("mysql error sql: %s, values: %v", err.Error(), values)
	}
	return nil
}

func (p *ServicePageInfoService) GetServicePageInfo(appkey string, versionid int64) (*ServicePageInfoItem, int) {
	var page *ServicePageInfoItem
	if val, ok := p.pages[appkey]; ok {
		page = val
	} else {
		//log.Warnf("appkey: %s is not exists", appkey)
		return nil, VERSION_ACTION_RESERVE
	}

	var action int
	if page.VersionId == versionid { //相同配置
		if page.Status == SERVICE_PAGE_STATUS_DELETE {
			action = VERSION_ACTION_DELETE
		} else {
			action = VERSION_ACTION_RESERVE
		}
	} else if page.VersionId > versionid {
		if page.Status == SERVICE_PAGE_STATUS_DELETE {
			action = VERSION_ACTION_RESERVE
		} else {
			action = VERSION_ACTION_UPDATE
		}
	} else {
		log.Warnf("GetServicePageInfo, client's versionid bigger than server's versionid, appkey: %s, versionid: %d, server's versionid: %d", appkey, versionid, page.VersionId)
		action = VERSION_ACTION_RESERVE
	}
	return page, action
}

func (p *ServicePageInfoService) CreateServicePageInfo(req *ServicePageInfoItem) (uint, string) {
	currentTick := time.Now().Unix()
	if req.EndTick <= currentTick || req.StartTick >= req.EndTick {
		return errorcode.EC_INVALID_TICK, "tick is wrong, publishTick should be smaller than endTick"
	}

	if page, ok := p.pages[req.AppKey]; ok {
		req.VersionId = page.VersionId + 1
	} else {
		req.VersionId = 1
	}
	req.Status = SERVICE_PAGE_STATUS_OK

	data := make(map[string]*utility.MySQLFieldValue)
	data["appkey"] = utility.NewMySQLFieldValue(req.AppKey, false)
	data["version_id"] = utility.NewMySQLFieldValue(req.VersionId, false)
	data["start_tick"] = utility.NewMySQLFieldValue(req.StartTick, false)
	data["end_tick"] = utility.NewMySQLFieldValue(req.EndTick, false)
	data["insert_tick"] = utility.NewMySQLFieldValue(time.Now().Unix(), false)
	data["update_tick"] = utility.NewMySQLFieldValue(time.Now().Unix(), false)
	if req.Items != nil {
		if b, err := json.Marshal(req.Items); err == nil {
			data["items"] = utility.NewMySQLFieldValue(string(b), false)
		} else {
			log.Warnf("invalid req.Items : %s", err.Error())
			return errorcode.EC_GL_INVALID_JSON_BODY, "items字段非法"
		}
	}
	data["status"] = utility.NewMySQLFieldValue(SERVICE_PAGE_STATUS_OK, false)
	mysqlHelper := db.GetMysqlHelper()
	if _, err := mysqlHelper.SaveRecord(data, "service_page"); err != nil {
		log.Errorf("CreateServicePageInfo error: %s, versionid: %d", err.Error(), req.VersionId)
		return errorcode.EC_GL_INTERNAL_ERROR, "CreateServicePageInfo error"
	}

	p.pages[req.AppKey] = req

	return errorcode.EC_GL_SUCCESS, "success"
}

//管理员获取服务页面配置信息列表
func (p *ServicePageInfoService) ServicePageInfoListMgr(start, length int, conditions map[string]interface{}, needTotalAll bool) ([]*ServicePageInfoItem, int) {
	dtq := datatable.NewDataTableQuery()
	dtq.SetTableName("service_page")
	dtq.SetPage(start, length)
	dtq.PushField(&datatable.FiledItem{Alias: "sid", Field: "sid", OrderBy: datatable.DESC})
	dtq.PushField(&datatable.FiledItem{Alias: "appkey", Field: "appkey"})
	dtq.PushField(&datatable.FiledItem{Alias: "version_id", Field: "version_id"})
	dtq.PushField(&datatable.FiledItem{Alias: "start_tick", Field: "start_tick"})
	dtq.PushField(&datatable.FiledItem{Alias: "end_tick", Field: "end_tick"})
	dtq.PushField(&datatable.FiledItem{Alias: "items", Field: "items"})
	dtq.PushField(&datatable.FiledItem{Alias: "status", Field: "status"})

	if conditions != nil {
		for k, v := range conditions {
			dtq.PushCondition(k, v)
		}
	}

	sql, values := dtq.GenerateSQL()
	mysqlHelper := db.GetMysqlHelper()
	rd := make([]*ServicePageInfoItem, 0, length)
	totalAll := 0
	if results, err := mysqlHelper.Query(sql, values...); err == nil {
		for _, dt := range results {
			page := &ServicePageInfoItem{}
			page.Sid = mysqlHelper.GetColInt64(dt, "sid")
			page.AppKey = mysqlHelper.GetColString(dt, "appkey")
			page.VersionId = mysqlHelper.GetColInt64(dt, "version_id")
			page.StartTick = mysqlHelper.GetColInt64(dt, "start_tick")
			page.EndTick = mysqlHelper.GetColInt64(dt, "end_tick")
			page.Status = mysqlHelper.GetColInt(dt, "status")
			args := mysqlHelper.GetColString(dt, "items")
			items := make([]map[string]interface{}, 0, 0)
			if err := json.Unmarshal([]byte(args), &items); err != nil {
				log.Warnf("items: %s Unmarshal error: %s", args, err.Error())
			}
			page.Items = items
			rd = append(rd, page)
		}
		if needTotalAll {
			s, v := dtq.GenerateTotalRecordSQL("total_records")
			if results, err := mysqlHelper.Query(s, v...); err == nil {
				if len(results) > 0 {
					totalAll = mysqlHelper.GetColInt(results[0], "total_records")
				}
			}
		}
	} else {
		log.Warnf("mysql error sql: %s, values: %v", err.Error(), values)
	}

	return rd, totalAll
}

func (p *ServicePageInfoService) DeleteServicePageInfo(sid int64) (uint, string) {
	if sid < 1 { //1.查看数据中的参数是否正确
		return errorcode.EC_SERVICEPAGEINFO_DELETE_INVALID_SID, "sid is wrong"
	}
	//2.删除对应的记录--   set status=0
	data := make(map[string]*utility.MySQLFieldValue)
	data["sid"] = utility.NewMySQLFieldValue(sid, false)
	data["status"] = utility.NewMySQLFieldValue(SERVICE_PAGE_STATUS_DELETE, true)
	mysqlHelper := db.GetMysqlHelper()
	if _, err := mysqlHelper.SaveRecord(data, "service_page"); err != nil {
		log.Errorf("DeleteServicePageInfo error: %s, sid: %d", err.Error(), sid)
		return errorcode.EC_GL_INTERNAL_ERROR, "DeleteServicePageInfo error"
	}
	return errorcode.EC_GL_SUCCESS, "success"

}
